package lspUtils;

import java.util.concurrent.LinkedBlockingQueue;

import lspUtils.*;


public class Enviar implements Runnable {
	
	private LinkedBlockingQueue<LspPacket> messageQueue = new LinkedBlockingQueue<>();
	private short sequenceNumber;
	
	
//	public Enviar(IConnector connector) {
//		this.connector = connector;
//	}
//	
	private short nextSequenceNumber() {
		sequenceNumber = (short) ((sequenceNumber + 1) % Short.MAX_VALUE); 
		return sequenceNumber; 
	}
	
	public void sendData(LspPack pack) {
		LspPacket packet = new LspPacket(MessageType.DATA, pack.getConnId(), nextSequenceNumber(), pack.getPayload());
		packet.setPacketStatus(PacketStatus.NEW);
		messageQueue.add(packet);
	}
	
	@Override
	public void run() {
		while (true) {
			LspPacket currentLspPacket = connector.getCurrentLspPacket();
			if (!messageQueue.isEmpty()) {
				if (currentLspPacket == null || currentLspPacket.getPacketStatus() == PacketStatus.ACK_RECEIVED || currentLspPacket.getPacketStatus() == PacketStatus.CANCELED) {
					sendNextPacket();
				} else if (currentLspPacket.getPacketStatus() == PacketStatus.RESEND) {
					resendPacket(currentLspPacket);
				}
			}
			
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				// interrupted: terminate execution
				return;
			}
		}
	}
	
	private void sendNextPacket() {
		LspPacket packet = messageQueue.poll();
		connector.sendPacket(packet);

		packet.setPacketStatus(PacketStatus.WAITING_ACK);
	}
	
	private void resendPacket(LspPacket packet) {
		connector.sendPacket(packet);
		
		packet.setPacketStatus(PacketStatus.WAITING_ACK);
	}

	public short currentSequenceNumber() {
		return sequenceNumber;
	}
	
}
